/**
 * 
 */
package kr.co.goodwilldd;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author IN-SOFT Inc. GoodwillDD(sylee@in-soft.co.kr)
 * 
 */
@SuppressWarnings("unused")
public class CheckSumUtil {

	private static final Logger logger = LoggerFactory
			.getLogger(CheckSumUtil.class);

	ArrayList<FileModel> result = null;
	String targetPath;

	public CheckSumUtil(String targetPath) {
		result = new ArrayList<FileModel>();
		this.targetPath = targetPath;
	}

	public void makeExcel(String excelFileName) throws Exception {
		checkSum(false);
		File excelFile = new File(excelFileName);
		WritableWorkbook workbook = Workbook.createWorkbook(excelFile);
		WritableSheet sheet = workbook.createSheet("checksum 목록", 0);
		try {
			List<Label> headers = new ArrayList<Label>();
			headers.add(new Label(1, 1, "path"));
			headers.add(new Label(2, 1, "filename"));
			headers.add(new Label(3, 1, "checksum"));
			headers.add(new Label(4, 1, "size"));
			headers.add(new Label(5, 1, "lastModified"));
			for (Label header : headers) {
				sheet.addCell(header);
			}
			int rowCount = 2;
			int cellCount = 1;
			for (FileModel fileModel : result) {
				sheet.addCell(new Label(cellCount++, rowCount, fileModel
						.getPath()));
				sheet.addCell(new Label(cellCount++, rowCount, fileModel
						.getFilename()));
				sheet.addCell(new Label(cellCount++, rowCount, fileModel
						.getChecksum()));
				sheet.addCell(new Label(cellCount++, rowCount, Long
						.toString(fileModel.getSize())));
				sheet.addCell(new Label(cellCount++, rowCount, fileModel
						.getLastModified()));
				cellCount = 1;
				rowCount++;
			}
		} finally {
			workbook.write();
			workbook.close();
		}
	}

	private String makeChecksum1(File file) throws Exception {
		MessageDigest md = MessageDigest.getInstance("MD5");
		FileInputStream fis = new FileInputStream(file);
		try {
			byte[] dataBytes = new byte[1024];

			int nread = 0;
			while ((nread = fis.read(dataBytes)) != -1) {
				md.update(dataBytes, 0, nread);
			}
			;
			byte[] mdbytes = md.digest();

			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < mdbytes.length; i++) {
				sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16)
						.substring(1));
			}

			return sb.toString();
		} finally {
			fis.close();
		}
	}

	private String makeChecksum2(File file) throws Exception {
		MessageDigest md = MessageDigest.getInstance("MD5");
		FileInputStream fis = new FileInputStream(file);
		try {
			byte[] dataBytes = new byte[1024];

			int nread = 0;
			while ((nread = fis.read(dataBytes)) != -1) {
				md.update(dataBytes, 0, nread);
			}
			;
			byte[] mdbytes = md.digest();

			StringBuffer hexString = new StringBuffer();
			for (int i = 0; i < mdbytes.length; i++) {
				String hex = Integer.toHexString(0xff & mdbytes[i]);
				if (hex.length() == 1)
					hexString.append('0');
				hexString.append(hex);
			}

			return hexString.toString();
		} finally {
			fis.close();
		}
	}

	public void checkSum(boolean logging) throws Exception {
		getFiles(targetPath);
		File file = null;
		for (FileModel fileModel : result) {
			file = fileModel.getFile();
			if (file.canRead()) {
				fileModel.setChecksum(makeChecksum1(file));
				if (logging)
					logger.debug("{}", fileModel.toString());
			}
		}
	}

	public static String convertLongToDate(long datetime) {
		Date date = new Date(datetime);
		Format format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return format.format(date).toString();
	}

	private static final FileFilter fileFilter = new FileFilter() {
		public boolean accept(File pathname) {
			return !pathname.getName().startsWith(".")
					&& !pathname.getName().endsWith("svn-base");
		}
	};

	private void getFiles(String source) {
		File dir = new File(source);
		File[] fileList = dir.listFiles(fileFilter);
		try {
			for (int i = 0; i < fileList.length; i++) {
				File file = fileList[i];
				if (file.isFile()) {
					result.add(new FileModel(targetPath, file));
				} else if (file.isDirectory()) {
					getFiles(file.getCanonicalPath().toString());
				}
			}
		} catch (IOException e) {
		}
	}
}
